package model

import (
	j_log "config-client-v1/init/j-log"
	"context"
	"encoding/json"
	"fmt"
	"github.com/simonvetter/modbus"
	"runtime/debug"
	"time"
)

type ModbusRTUConfig struct {
	PortName        string `json:"port_name"`         // 串口名称 COM1,COM2...
	BaudRate        uint   `json:"baud_rate"`         // 波特率 9600
	DataBits        uint   `json:"data_bits"`         // 数据位 8
	StopBits        uint   `json:"stop_bits"`         // 停止位 1
	MinimumReadSize uint   `json:"minimum_read_size"` // 最小读取字节 4
	ParityMode      uint   `json:"parity_mode"`       // 奇偶检验 0.NONE 1.ODD 2.EVEN
	ConnectTimeout  int    `json:"connect_timeout"`   // 连接超时时间 (单位ms)
	ResponseTimeout int    `json:"response_timeout"`  // 响应超时时间 (单位ms)
}

func (ppe *PPE) RunModbusRTUClient() {
	defer func() {
		if err := recover(); err != nil {
			j_log.LogError([]interface{}{"RunModbusRTUClient panic", err})
			fmt.Println(string(debug.Stack()))
		}
		if ppe.RunningState == 3 {
			ppe.RunningState = 4 // 设备停止
			ppe.Detail = "已停止"
			_ = ppe.UpdateRunningState(4, "已停止")
		} else {
			ppe.RunningState = 0 // 设备异常
			_ = ppe.UpdateRunningState(0, "设备异常")
		}
		ppe.UnRegister()
	}()
	ppe.Register()

	config := ModbusRTUConfig{}
	err := json.Unmarshal([]byte(ppe.Config), &config)
	if err != nil {
		j_log.LogError([]interface{}{config.PortName, "ModbusRTUConfig json解析失败:" + err.Error()})
		return
	}
	url := "rtu://" + config.PortName
	client, err := modbus.NewClient(&modbus.ClientConfiguration{
		URL:      url,
		Speed:    config.BaudRate,
		DataBits: config.DataBits,
		Parity:   config.ParityMode,
		StopBits: config.StopBits,
		Timeout:  time.Duration(config.ConnectTimeout) * time.Millisecond,
	})
	if err != nil {
		j_log.LogError([]interface{}{url, "modbus.NewClient error:" + err.Error()})
		ppe.Detail = fmt.Sprintf("%v %v modbus.NewClient error: %v", ppe.Name, url, err.Error())
		return
	}
	err = client.Open()
	if err != nil {
		j_log.LogError([]interface{}{url, "modbus client.Open error:" + err.Error()})
		ppe.Detail = fmt.Sprintf("%v %v modbus client.Open error: %v", ppe.Name, url, err.Error())
		return
	}
	defer client.Close()
	j_log.LogInfo([]interface{}{fmt.Sprintf("【已启动】%s:%s", ppe.ProtocolName, ppe.Name)})
	ppe.RunningState = 2 // 启动成功
	ppe.ModbusRTUClient = client
	ppe.Detail = "已启动"
	_ = ppe.UpdateRunningState(2, "已启动")

	ctxModbus, cancel := context.WithCancel(context.Background())
	defer cancel()

	stopChan := make(chan int, 1000)
	for _, frame := range ppe.FrameList {
		if frame.Status != 1 {
			continue
		}
		switch frame.FunctionCode {
		case "01":
			go modbus0x01(ctxModbus, ppe, client, frame, stopChan)
		case "02":
			go modbus0x02(ctxModbus, ppe, client, frame, stopChan)
		case "03":
			go modbus0x03(ctxModbus, ppe, client, frame, stopChan)
		case "04":
			go modbus0x04(ctxModbus, ppe, client, frame, stopChan)
		case "05":
			go modbus0x05(ctxModbus, ppe, client, frame, stopChan)
		case "06":
			go modbus0x06(ctxModbus, ppe, client, frame, stopChan)
		case "0F":
			go modbus0x0F(ctxModbus, ppe, client, frame, stopChan)
		case "10":
			go modbus0x10(ctxModbus, ppe, client, frame, stopChan)
		default:
			j_log.LogInfo([]interface{}{fmt.Sprintf("[%s][%s][%s] 无效的功能码", ppe.Name, frame.Name, frame.FunctionCode)})
			continue
		}
		time.Sleep(100 * time.Millisecond)
	}

	for {
		if ppe.RunningState == 3 {
			return
		}
		time.Sleep(500 * time.Millisecond)
	}

}
